/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
 C      sys_timer.c
 C      Application Name: tcss422-project2
 C      Programmers Names: Evan Phillips, Lucas Cowell, Tony Butterfield
 C      Date created:   May 24, 2011
 C      Date Completed: 
 C      Brief Description: 
 C
 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/
#include <stdlib.h>
#include <stdio.h>
#include "system_timer.h"
#include "definitions.h"
#include "cpu_sim.h"
#include "io_device.h"

/*=================================================================================================
 =  Comment block for function: timer_init()
 =  Programmer names: Evan Phillips, Lucas Cowell, Tony Butterfield
 =  Final test and approval date:
 =  Synopsis:
 =      Timer timer_init(int, CPU, IODevice, IODevice, IODevice)
 =      Return value ranges: pointer to timer
 =      Parameter value ranges: int interupt interval, pointer to cpu, pointer to keyboard, pointer
 =                  to disk, pointer to video
 =      Error conditions: N/a
 =  Initializes a system timer.
 =
 ==================================================================================================*/
Timer timer_init(int timer_interval, CPU cpu)
{
    Timer timer = (Timer) malloc(sizeof(SysTimerStr));

    timer->tick = 0;
    timer->interval = timer_interval;
    timer->cpu = cpu;
    return timer;
}

/*=================================================================================================
 =  Comment block for function: timer_start()
 =  Programmer names: Evan Phillips, Lucas Cowell, Tony Butterfield
 =  Final test and approval date:
 =  Synopsis:
 =      int timer_start(Timer)
 =      Return value ranges: 0 for success, otherwise error code
 =      Parameter value ranges: pointer to timer
 =      Error conditions: NULL_POINTER_ERROR
 =  Starts the system timer running.
 =
 ==================================================================================================*/
int timer_start(Timer timer)
{
    if (timer == NULL) return NULL_POINTER_ERROR;

    while (TRUE /* TODO: while the 'q' key has not been hit? */)
    {
        timer->tick++;
        timer_tick(timer);
        timer->tick = timer->tick % timer->interval;    // reset to zero
    }

    return 0;
}

/*=================================================================================================
 =  Comment block for function: timer_step()
 =  Programmer names: Evan Phillips, Lucas Cowell, Tony Butterfield
 =  Final test and approval date:
 =  Synopsis:
 =      int timer_step(Timer)
 =      Return value ranges: 0 for success, otherwise error code
 =      Parameter value ranges: pointer to timer
 =      Error conditions: NULL_POINTER_ERROR
 =  runs through 1 timer 'tick'
 =
 ==================================================================================================*/
int timer_step(Timer timer)
{
    if (timer == NULL) return NULL_POINTER_ERROR;

    timer->tick++;
    timer_tick(timer);
    timer->tick = timer->tick % timer->interval;    // reset to zero
    return 0;
}

/*=================================================================================================
 =  Comment block for function: timer_tick()
 =  Programmer names: Evan Phillips, Lucas Cowell, Tony Butterfield
 =  Final test and approval date:
 =  Synopsis:
 =      int timer_tick(Timer)
 =      Return value ranges: 0 for success, otherwise error code
 =      Parameter value ranges: pointer to timer
 =      Error conditions: NULL_POINTER_ERROR
 =  ticks the cpu, keyboard, disk, and video. .
 =
 ==================================================================================================*/
int timer_tick(Timer timer)
{
    if (timer == NULL) return NULL_POINTER_ERROR;

    if (timer->tick == timer->interval)
    {
        timer_Interrupt(timer);
    }

    iodev_tick(timer->cpu->kbd);
    iodev_tick(timer->cpu->dsk);
    iodev_tick(timer->cpu->vid);

    cpu_tick(timer->cpu);       // cpu ticks last so it can react to any interrupts thrown.


    return 0;
}

/*=================================================================================================
 =  Comment block for function: timer_Interrupt()
 =  Programmer names: Evan Phillips, Lucas Cowell, Tony Butterfield
 =  Final test and approval date:
 =  Synopsis:
 =      int timer_Interrupt(Timer)
 =      Return value ranges: 0 for success, otherwise error code
 =      Parameter value ranges: pointer to timer
 =      Error conditions: NULL_POINTER_ERROR
 =  sends a SYS_TIMER_INTERRUPT to the Interrupt Controller (in this sim, part of the cpu struct)
 =
 ==================================================================================================*/
int timer_Interrupt(Timer timer)
{
    if (timer == NULL) return NULL_POINTER_ERROR;

    timer->cpu->interrupt_controller |= SYS_TIMER_INTERRUPT;
    return 0;
}
